//
//  ApiManager.swift
//  FaceVerify
//
//  Created by duzexu on 2017/3/2.
//  Copyright © 2017年 duzexu. All rights reserved.
//

import UIKit
import Moya
import HandyJSON
import MoyaSugar
import RxSwift

enum ApiManager {
    case uploadImage(String?)
    case verifyFace(faceId1:String, faceId2:String)
}

extension ApiManager: SugarTargetType {
    /// The target's base `URL`.
    var baseURL: URL {
        return URL.init(string: "https://westus.api.cognitive.microsoft.com/face/v1.0")!
    }
    
    var route: Route {
        switch self {
        case .uploadImage:
            return .post("/detect")
        case .verifyFace:
            return .post("/verify")
        }
    }
    
    var url: URL {
        return self.defaultURL
    }
    
    var httpHeaderFields: [String : String]? {
        switch self {
        case .uploadImage:
            return ["Content-Type":"application/octet-stream", "Ocp-Apim-Subscription-Key":"363b334ae55a4514867e33d8c8ee24ca"]
        case .verifyFace:
            return ["Content-Type":"application/json", "Ocp-Apim-Subscription-Key":"363b334ae55a4514867e33d8c8ee24ca"]
        }
    }
    
    /// The parameters to be incoded in the request.
    var params: Parameters? {
        switch self {
        case .uploadImage:
            return URLEncoding(destination: .queryString) => ["returnFaceAttributes":"age,gender,smile,glasses"]
        case .verifyFace(let faceId1,let faceId2):
            return JSONEncoding() => ["faceId1":faceId1,"faceId2":faceId2]
        }
    }
    
    /// Provides stub data for use in testing.
    var sampleData: Data {
        return "".data(using: .utf8)!
    }
    
    /// The type of HTTP task to be performed.
    var task: Task {
        switch self {
        case .uploadImage(let url):
            guard  url != nil else {
                return .request;
            }
            let type = UploadType.file(NSURL.fileURL(withPath: url!))
            return .upload(type)
        case .verifyFace:
            return .request
        }
    }
    
    /// Whether or not to perform Alamofire validation. Defaults to `false`.
    var validate: Bool {
        return false
    }
}

// MARK: - Model Extention
extension ObservableType where E == Response {
    public func mapModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
        return flatMap { response -> Observable<T> in
            return Observable.just(response.mapModel(T.self))
        }
    }
    
    public func mapArray<T: HandyJSON>(_ type: T.Type) -> Observable<Array<T>> {
        return flatMap { response -> Observable<Array<T>> in
            return Observable.just(response.mapArray(T.self))
        }
    }
}

extension Response {
    func mapModel<T: HandyJSON>(_ type: T.Type) -> T {
        let jsonString = String.init(data: data, encoding: .utf8)
        return JSONDeserializer<T>.deserializeFrom(json: jsonString)!
    }
    
    func mapArray<T: HandyJSON>(_ type: T.Type) -> [T] {
        let jsonString = String.init(data: data, encoding: .utf8)
        return JSONDeserializer<T>.deserializeModelArrayFrom(json: jsonString)! as! [T]
    }
}
